//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_spi(SotoInternal) import SotoCore

extension NetworkMonitor {
    // MARK: Enums

    public enum AddressFamily: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case ipv4 = "IPV4"
        case ipv6 = "IPV6"
        public var description: String { return self.rawValue }
    }

    public enum MonitorState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "ACTIVE"
        case deleting = "DELETING"
        case error = "ERROR"
        case inactive = "INACTIVE"
        case pending = "PENDING"
        public var description: String { return self.rawValue }
    }

    public enum ProbeState: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case active = "ACTIVE"
        case deleted = "DELETED"
        case deleting = "DELETING"
        case error = "ERROR"
        case inactive = "INACTIVE"
        case pending = "PENDING"
        public var description: String { return self.rawValue }
    }

    public enum `Protocol`: String, CustomStringConvertible, Codable, Sendable, CodingKeyRepresentable {
        case icmp = "ICMP"
        case tcp = "TCP"
        public var description: String { return self.rawValue }
    }

    // MARK: Shapes

    public struct CreateMonitorInput: AWSEncodableShape {
        /// The time, in seconds, that metrics are aggregated and sent to Amazon CloudWatch. Valid values are either 30 or 60.  60 is the default if no period is chosen.
        public let aggregationPeriod: Int64?
        /// Unique, case-sensitive identifier to ensure the idempotency of the request. Only returned if a client token was provided in the request.
        public let clientToken: String?
        /// The name identifying the monitor. It can contain only letters, underscores (_), or dashes (-), and can be up to 200 characters.
        public let monitorName: String
        /// Displays a list of all of the probes created for a monitor.
        public let probes: [CreateMonitorProbeInput]?
        /// The list of key-value pairs created and assigned to the monitor.
        public let tags: [String: String]?

        @inlinable
        public init(aggregationPeriod: Int64? = nil, clientToken: String? = CreateMonitorInput.idempotencyToken(), monitorName: String, probes: [CreateMonitorProbeInput]? = nil, tags: [String: String]? = nil) {
            self.aggregationPeriod = aggregationPeriod
            self.clientToken = clientToken
            self.monitorName = monitorName
            self.probes = probes
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.aggregationPeriod, name: "aggregationPeriod", parent: name, min: 30)
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            try self.probes?.forEach {
                try $0.validate(name: "\(name).probes[]")
            }
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case aggregationPeriod = "aggregationPeriod"
            case clientToken = "clientToken"
            case monitorName = "monitorName"
            case probes = "probes"
            case tags = "tags"
        }
    }

    public struct CreateMonitorOutput: AWSDecodableShape {
        /// The number of seconds that metrics are aggregated by and sent to Amazon CloudWatch. This will be either 30 or 60.
        public let aggregationPeriod: Int64?
        /// The ARN of the monitor.
        public let monitorArn: String
        /// The name of the monitor.
        public let monitorName: String
        /// The state of the monitor.
        public let state: MonitorState
        /// The list of key-value pairs assigned to the monitor.
        public let tags: [String: String]?

        @inlinable
        public init(aggregationPeriod: Int64? = nil, monitorArn: String, monitorName: String, state: MonitorState, tags: [String: String]? = nil) {
            self.aggregationPeriod = aggregationPeriod
            self.monitorArn = monitorArn
            self.monitorName = monitorName
            self.state = state
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case aggregationPeriod = "aggregationPeriod"
            case monitorArn = "monitorArn"
            case monitorName = "monitorName"
            case state = "state"
            case tags = "tags"
        }
    }

    public struct CreateMonitorProbeInput: AWSEncodableShape {
        /// The destination IP address. This must be either IPV4 or IPV6.
        public let destination: String
        /// The port associated with the destination. This is required only if the protocol is TCP and must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The size of the packets sent between the source and destination. This must be a number between 56 and 8500.
        public let packetSize: Int?
        /// The list of key-value pairs created and assigned to the monitor.
        public let probeTags: [String: String]?
        /// The protocol used for the network traffic between the source and destination. This must be either TCP or ICMP.
        public let `protocol`: `Protocol`
        /// The ARN of the subnet.
        public let sourceArn: String

        @inlinable
        public init(destination: String, destinationPort: Int? = nil, packetSize: Int? = nil, probeTags: [String: String]? = nil, protocol: `Protocol`, sourceArn: String) {
            self.destination = destination
            self.destinationPort = destinationPort
            self.packetSize = packetSize
            self.probeTags = probeTags
            self.`protocol` = `protocol`
            self.sourceArn = sourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.destination, name: "destination", parent: name, max: 255)
            try self.validate(self.destination, name: "destination", parent: name, min: 1)
            try self.validate(self.destinationPort, name: "destinationPort", parent: name, max: 65536)
            try self.validate(self.destinationPort, name: "destinationPort", parent: name, min: 0)
            try self.validate(self.packetSize, name: "packetSize", parent: name, max: 8500)
            try self.validate(self.packetSize, name: "packetSize", parent: name, min: 56)
            try self.probeTags?.forEach {
                try validate($0.key, name: "probeTags.key", parent: name, max: 128)
                try validate($0.key, name: "probeTags.key", parent: name, min: 1)
                try validate($0.value, name: "probeTags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.probeTags, name: "probeTags", parent: name, max: 200)
            try self.validate(self.sourceArn, name: "sourceArn", parent: name, max: 2048)
            try self.validate(self.sourceArn, name: "sourceArn", parent: name, min: 20)
            try self.validate(self.sourceArn, name: "sourceArn", parent: name, pattern: "^arn:.*$")
        }

        private enum CodingKeys: String, CodingKey {
            case destination = "destination"
            case destinationPort = "destinationPort"
            case packetSize = "packetSize"
            case probeTags = "probeTags"
            case `protocol` = "protocol"
            case sourceArn = "sourceArn"
        }
    }

    public struct CreateProbeInput: AWSEncodableShape {
        /// Unique, case-sensitive identifier to ensure the idempotency of the request. Only returned if a client token was provided in the request.
        public let clientToken: String?
        /// The name of the monitor to associated with the probe.
        public let monitorName: String
        /// Describes the details of an individual probe for a monitor.
        public let probe: ProbeInput
        /// The list of key-value pairs created and assigned to the probe.
        public let tags: [String: String]?

        @inlinable
        public init(clientToken: String? = CreateProbeInput.idempotencyToken(), monitorName: String, probe: ProbeInput, tags: [String: String]? = nil) {
            self.clientToken = clientToken
            self.monitorName = monitorName
            self.probe = probe
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encodeIfPresent(self.clientToken, forKey: .clientToken)
            request.encodePath(self.monitorName, key: "monitorName")
            try container.encode(self.probe, forKey: .probe)
            try container.encodeIfPresent(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            try self.probe.validate(name: "\(name).probe")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken = "clientToken"
            case probe = "probe"
            case tags = "tags"
        }
    }

    public struct CreateProbeOutput: AWSDecodableShape {
        /// Indicates whether the IP address is IPV4 or IPV6.
        public let addressFamily: AddressFamily?
        /// The time and date that the probe was created.
        public let createdAt: Date?
        /// The destination IP address for the monitor. This must be either an IPv4 or IPv6 address.
        public let destination: String
        /// The port associated with the destination. This is required only if the protocol is TCP and must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The time and date when the probe was last modified.
        public let modifiedAt: Date?
        /// The size of the packets sent between the source and destination. This must be a number between 56 and 8500.
        public let packetSize: Int?
        /// The ARN of the probe.
        public let probeArn: String?
        /// The ID of the probe for which details are returned.
        public let probeId: String?
        /// The protocol used for the network traffic between the source and destination. This must be either TCP or ICMP.
        public let `protocol`: `Protocol`
        /// The ARN of the probe.
        public let sourceArn: String
        /// The state of the probe.
        public let state: ProbeState?
        /// The list of key-value pairs assigned to the probe.
        public let tags: [String: String]?
        /// The ID of the source VPC or subnet.
        public let vpcId: String?

        @inlinable
        public init(addressFamily: AddressFamily? = nil, createdAt: Date? = nil, destination: String, destinationPort: Int? = nil, modifiedAt: Date? = nil, packetSize: Int? = nil, probeArn: String? = nil, probeId: String? = nil, protocol: `Protocol`, sourceArn: String, state: ProbeState? = nil, tags: [String: String]? = nil, vpcId: String? = nil) {
            self.addressFamily = addressFamily
            self.createdAt = createdAt
            self.destination = destination
            self.destinationPort = destinationPort
            self.modifiedAt = modifiedAt
            self.packetSize = packetSize
            self.probeArn = probeArn
            self.probeId = probeId
            self.`protocol` = `protocol`
            self.sourceArn = sourceArn
            self.state = state
            self.tags = tags
            self.vpcId = vpcId
        }

        private enum CodingKeys: String, CodingKey {
            case addressFamily = "addressFamily"
            case createdAt = "createdAt"
            case destination = "destination"
            case destinationPort = "destinationPort"
            case modifiedAt = "modifiedAt"
            case packetSize = "packetSize"
            case probeArn = "probeArn"
            case probeId = "probeId"
            case `protocol` = "protocol"
            case sourceArn = "sourceArn"
            case state = "state"
            case tags = "tags"
            case vpcId = "vpcId"
        }
    }

    public struct DeleteMonitorInput: AWSEncodableShape {
        /// The name of the monitor to delete.
        public let monitorName: String

        @inlinable
        public init(monitorName: String) {
            self.monitorName = monitorName
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.monitorName, key: "monitorName")
        }

        public func validate(name: String) throws {
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteMonitorOutput: AWSDecodableShape {
        public init() {}
    }

    public struct DeleteProbeInput: AWSEncodableShape {
        /// The name of the monitor to delete.
        public let monitorName: String
        /// The ID of the probe to delete.
        public let probeId: String

        @inlinable
        public init(monitorName: String, probeId: String) {
            self.monitorName = monitorName
            self.probeId = probeId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.monitorName, key: "monitorName")
            request.encodePath(self.probeId, key: "probeId")
        }

        public func validate(name: String) throws {
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            try self.validate(self.probeId, name: "probeId", parent: name, pattern: "^probe-[a-z0-9A-Z-]{21,64}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteProbeOutput: AWSDecodableShape {
        public init() {}
    }

    public struct GetMonitorInput: AWSEncodableShape {
        /// The name of the monitor that details are returned for.
        public let monitorName: String

        @inlinable
        public init(monitorName: String) {
            self.monitorName = monitorName
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.monitorName, key: "monitorName")
        }

        public func validate(name: String) throws {
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetMonitorOutput: AWSDecodableShape {
        /// The aggregation period for the specified monitor.
        public let aggregationPeriod: Int64
        /// The time and date when the monitor was created.
        public let createdAt: Date
        /// The time and date when the monitor was last modified.
        public let modifiedAt: Date
        /// The ARN of the selected monitor.
        public let monitorArn: String
        /// The name of the monitor.
        public let monitorName: String
        /// The details about each probe associated with that monitor.
        public let probes: [Probe]?
        /// Lists the status of the state of each monitor.
        public let state: MonitorState
        /// The list of key-value pairs assigned to the monitor.
        public let tags: [String: String]?

        @inlinable
        public init(aggregationPeriod: Int64, createdAt: Date, modifiedAt: Date, monitorArn: String, monitorName: String, probes: [Probe]? = nil, state: MonitorState, tags: [String: String]? = nil) {
            self.aggregationPeriod = aggregationPeriod
            self.createdAt = createdAt
            self.modifiedAt = modifiedAt
            self.monitorArn = monitorArn
            self.monitorName = monitorName
            self.probes = probes
            self.state = state
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case aggregationPeriod = "aggregationPeriod"
            case createdAt = "createdAt"
            case modifiedAt = "modifiedAt"
            case monitorArn = "monitorArn"
            case monitorName = "monitorName"
            case probes = "probes"
            case state = "state"
            case tags = "tags"
        }
    }

    public struct GetProbeInput: AWSEncodableShape {
        /// The name of the monitor associated with the probe. Run ListMonitors to get a list of monitor names.
        public let monitorName: String
        /// The ID of the probe to get information about. Run GetMonitor action to get a list of probes and probe IDs for the  monitor.
        public let probeId: String

        @inlinable
        public init(monitorName: String, probeId: String) {
            self.monitorName = monitorName
            self.probeId = probeId
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.monitorName, key: "monitorName")
            request.encodePath(self.probeId, key: "probeId")
        }

        public func validate(name: String) throws {
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            try self.validate(self.probeId, name: "probeId", parent: name, pattern: "^probe-[a-z0-9A-Z-]{21,64}$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetProbeOutput: AWSDecodableShape {
        /// Indicates whether the IP address is IPV4 or IPV6.
        public let addressFamily: AddressFamily?
        /// The time and date that the probe was created.
        public let createdAt: Date?
        /// The destination IP address for the monitor. This must be either an IPv4 or IPv6 address.
        public let destination: String
        /// The port associated with the destination. This is required only if the protocol is TCP and must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The time and date that the probe was last modified.
        public let modifiedAt: Date?
        /// The size of the packets sent between the source and destination. This must be a number between 56 and 8500.
        public let packetSize: Int?
        /// The ARN of the probe.
        public let probeArn: String?
        /// The ID of the probe for which details are returned.
        public let probeId: String?
        /// The protocol used for the network traffic between the source and destination. This must be either TCP or ICMP.
        public let `protocol`: `Protocol`
        /// The ARN of the probe.
        public let sourceArn: String
        /// The state of the probe.
        public let state: ProbeState?
        /// The list of key-value pairs assigned to the probe.
        public let tags: [String: String]?
        /// The ID of the source VPC or subnet.
        public let vpcId: String?

        @inlinable
        public init(addressFamily: AddressFamily? = nil, createdAt: Date? = nil, destination: String, destinationPort: Int? = nil, modifiedAt: Date? = nil, packetSize: Int? = nil, probeArn: String? = nil, probeId: String? = nil, protocol: `Protocol`, sourceArn: String, state: ProbeState? = nil, tags: [String: String]? = nil, vpcId: String? = nil) {
            self.addressFamily = addressFamily
            self.createdAt = createdAt
            self.destination = destination
            self.destinationPort = destinationPort
            self.modifiedAt = modifiedAt
            self.packetSize = packetSize
            self.probeArn = probeArn
            self.probeId = probeId
            self.`protocol` = `protocol`
            self.sourceArn = sourceArn
            self.state = state
            self.tags = tags
            self.vpcId = vpcId
        }

        private enum CodingKeys: String, CodingKey {
            case addressFamily = "addressFamily"
            case createdAt = "createdAt"
            case destination = "destination"
            case destinationPort = "destinationPort"
            case modifiedAt = "modifiedAt"
            case packetSize = "packetSize"
            case probeArn = "probeArn"
            case probeId = "probeId"
            case `protocol` = "protocol"
            case sourceArn = "sourceArn"
            case state = "state"
            case tags = "tags"
            case vpcId = "vpcId"
        }
    }

    public struct ListMonitorsInput: AWSEncodableShape {
        /// The maximum number of results to return with a single call.
        /// 	To retrieve the remaining results, make another call with the returned nextToken value. If MaxResults is given a value larger than 100, only 100 results are returned.
        public let maxResults: Int?
        /// The token for the next page of results.
        public let nextToken: String?
        /// The list of all monitors and their states.
        public let state: String?

        @inlinable
        public init(maxResults: Int? = nil, nextToken: String? = nil, state: String? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.state = state
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodeQuery(self.maxResults, key: "maxResults")
            request.encodeQuery(self.nextToken, key: "nextToken")
            request.encodeQuery(self.state, key: "state")
        }

        public func validate(name: String) throws {
            try self.validate(self.maxResults, name: "maxResults", parent: name, max: 25)
            try self.validate(self.maxResults, name: "maxResults", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 4096)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListMonitorsOutput: AWSDecodableShape {
        /// Lists individual details about each of your monitors.
        public let monitors: [MonitorSummary]
        /// The token for the next page of results.
        public let nextToken: String?

        @inlinable
        public init(monitors: [MonitorSummary], nextToken: String? = nil) {
            self.monitors = monitors
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case monitors = "monitors"
            case nextToken = "nextToken"
        }
    }

    public struct ListTagsForResourceInput: AWSEncodableShape {
        /// The
        public let resourceArn: String

        @inlinable
        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:.*$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceOutput: AWSDecodableShape {
        /// Lists the tags assigned to the resource.
        public let tags: [String: String]?

        @inlinable
        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct MonitorSummary: AWSDecodableShape {
        /// The time, in seconds, that metrics are collected and sent to Amazon CloudWatch. Valid values are either 30 or 60.
        public let aggregationPeriod: Int64?
        /// The ARN of the monitor.
        public let monitorArn: String
        /// The name of the monitor.
        public let monitorName: String
        /// The state of the monitor.
        public let state: MonitorState
        /// The list of key-value pairs assigned to the monitor.
        public let tags: [String: String]?

        @inlinable
        public init(aggregationPeriod: Int64? = nil, monitorArn: String, monitorName: String, state: MonitorState, tags: [String: String]? = nil) {
            self.aggregationPeriod = aggregationPeriod
            self.monitorArn = monitorArn
            self.monitorName = monitorName
            self.state = state
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case aggregationPeriod = "aggregationPeriod"
            case monitorArn = "monitorArn"
            case monitorName = "monitorName"
            case state = "state"
            case tags = "tags"
        }
    }

    public struct Probe: AWSDecodableShape {
        /// The IPv4 or IPv6 address for the probe.
        public let addressFamily: AddressFamily?
        /// The time and date the probe was created.
        public let createdAt: Date?
        /// The destination for the probe. This should be either an IPV4 or IPV6.
        public let destination: String
        /// The destination port for the probe. This is required only if the protocol is TCP and must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The time and date that the probe was last modified.
        public let modifiedAt: Date?
        /// The size of the packets traveling between the source and destination. This must be a number between 56 and
        public let packetSize: Int?
        /// The ARN of the probe.
        public let probeArn: String?
        /// The ID of the probe.
        public let probeId: String?
        /// The network protocol for the destination. This can be either TCP or ICMP. If the protocol is TCP, then port is also required.
        public let `protocol`: `Protocol`
        /// The ARN of the probe source subnet.
        public let sourceArn: String
        /// The state of the probe.
        public let state: ProbeState?
        /// The list of key-value pairs created and assigned to the probe.
        public let tags: [String: String]?
        /// The ID of the source VPC subnet.
        public let vpcId: String?

        @inlinable
        public init(addressFamily: AddressFamily? = nil, createdAt: Date? = nil, destination: String, destinationPort: Int? = nil, modifiedAt: Date? = nil, packetSize: Int? = nil, probeArn: String? = nil, probeId: String? = nil, protocol: `Protocol`, sourceArn: String, state: ProbeState? = nil, tags: [String: String]? = nil, vpcId: String? = nil) {
            self.addressFamily = addressFamily
            self.createdAt = createdAt
            self.destination = destination
            self.destinationPort = destinationPort
            self.modifiedAt = modifiedAt
            self.packetSize = packetSize
            self.probeArn = probeArn
            self.probeId = probeId
            self.`protocol` = `protocol`
            self.sourceArn = sourceArn
            self.state = state
            self.tags = tags
            self.vpcId = vpcId
        }

        private enum CodingKeys: String, CodingKey {
            case addressFamily = "addressFamily"
            case createdAt = "createdAt"
            case destination = "destination"
            case destinationPort = "destinationPort"
            case modifiedAt = "modifiedAt"
            case packetSize = "packetSize"
            case probeArn = "probeArn"
            case probeId = "probeId"
            case `protocol` = "protocol"
            case sourceArn = "sourceArn"
            case state = "state"
            case tags = "tags"
            case vpcId = "vpcId"
        }
    }

    public struct ProbeInput: AWSEncodableShape {
        /// The destination IP address. This must be either IPV4 or IPV6.
        public let destination: String
        /// The port associated with the destination. This is required only if the protocol is TCP and must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The size of the packets sent between the source and destination. This must be a number between 56 and 8500.
        public let packetSize: Int?
        /// The protocol used for the network traffic between the source and destination. This must be either TCP or ICMP.
        public let `protocol`: `Protocol`
        /// The ARN of the subnet.
        public let sourceArn: String
        /// The list of key-value pairs created and assigned to the monitor.
        public let tags: [String: String]?

        @inlinable
        public init(destination: String, destinationPort: Int? = nil, packetSize: Int? = nil, protocol: `Protocol`, sourceArn: String, tags: [String: String]? = nil) {
            self.destination = destination
            self.destinationPort = destinationPort
            self.packetSize = packetSize
            self.`protocol` = `protocol`
            self.sourceArn = sourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.destination, name: "destination", parent: name, max: 255)
            try self.validate(self.destination, name: "destination", parent: name, min: 1)
            try self.validate(self.destinationPort, name: "destinationPort", parent: name, max: 65536)
            try self.validate(self.destinationPort, name: "destinationPort", parent: name, min: 0)
            try self.validate(self.packetSize, name: "packetSize", parent: name, max: 8500)
            try self.validate(self.packetSize, name: "packetSize", parent: name, min: 56)
            try self.validate(self.sourceArn, name: "sourceArn", parent: name, max: 2048)
            try self.validate(self.sourceArn, name: "sourceArn", parent: name, min: 20)
            try self.validate(self.sourceArn, name: "sourceArn", parent: name, pattern: "^arn:.*$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case destination = "destination"
            case destinationPort = "destinationPort"
            case packetSize = "packetSize"
            case `protocol` = "protocol"
            case sourceArn = "sourceArn"
            case tags = "tags"
        }
    }

    public struct TagResourceInput: AWSEncodableShape {
        /// The ARN of the monitor or probe to tag.
        public let resourceArn: String
        /// The list of key-value pairs assigned to the monitor or probe.
        public let tags: [String: String]

        @inlinable
        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            try container.encode(self.tags, forKey: .tags)
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:.*$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case tags = "tags"
        }
    }

    public struct TagResourceOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UntagResourceInput: AWSEncodableShape {
        /// The ARN of the monitor or probe that the tag should be removed from.
        public let resourceArn: String
        /// The key-value pa
        public let tagKeys: [String]

        @inlinable
        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            _ = encoder.container(keyedBy: CodingKeys.self)
            request.encodePath(self.resourceArn, key: "resourceArn")
            request.encodeQuery(self.tagKeys, key: "tagKeys")
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 2048)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 20)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:.*$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 200)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceOutput: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateMonitorInput: AWSEncodableShape {
        /// The aggregation time, in seconds, to change to. This must be either 30 or 60.
        public let aggregationPeriod: Int64
        /// The name of the monitor to update.
        public let monitorName: String

        @inlinable
        public init(aggregationPeriod: Int64, monitorName: String) {
            self.aggregationPeriod = aggregationPeriod
            self.monitorName = monitorName
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(self.aggregationPeriod, forKey: .aggregationPeriod)
            request.encodePath(self.monitorName, key: "monitorName")
        }

        public func validate(name: String) throws {
            try self.validate(self.aggregationPeriod, name: "aggregationPeriod", parent: name, min: 30)
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case aggregationPeriod = "aggregationPeriod"
        }
    }

    public struct UpdateMonitorOutput: AWSDecodableShape {
        /// The changed aggregation period.
        public let aggregationPeriod: Int64?
        /// The ARN of the monitor that was updated.
        public let monitorArn: String
        /// The name of the monitor that was updated.
        public let monitorName: String
        /// The state of the updated monitor.
        public let state: MonitorState
        /// The list of key-value pairs associated with the monitor.
        public let tags: [String: String]?

        @inlinable
        public init(aggregationPeriod: Int64? = nil, monitorArn: String, monitorName: String, state: MonitorState, tags: [String: String]? = nil) {
            self.aggregationPeriod = aggregationPeriod
            self.monitorArn = monitorArn
            self.monitorName = monitorName
            self.state = state
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case aggregationPeriod = "aggregationPeriod"
            case monitorArn = "monitorArn"
            case monitorName = "monitorName"
            case state = "state"
            case tags = "tags"
        }
    }

    public struct UpdateProbeInput: AWSEncodableShape {
        /// The updated IP address for the probe destination. This must be either an IPv4 or IPv6 address.
        public let destination: String?
        /// The updated port for the probe destination. This is required only if the protocol is TCP and must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The name of the monitor that the probe was updated for.
        public let monitorName: String
        /// he updated packets size for network traffic between the source and destination. This must be a number between 56 and 8500.
        public let packetSize: Int?
        /// The ID of the probe to update.
        public let probeId: String
        /// The updated network protocol for the destination. This can be either TCP or ICMP. If the protocol is TCP, then port is also required.
        public let `protocol`: `Protocol`?
        /// The state of the probe update.
        public let state: ProbeState?

        @inlinable
        public init(destination: String? = nil, destinationPort: Int? = nil, monitorName: String, packetSize: Int? = nil, probeId: String, protocol: `Protocol`? = nil, state: ProbeState? = nil) {
            self.destination = destination
            self.destinationPort = destinationPort
            self.monitorName = monitorName
            self.packetSize = packetSize
            self.probeId = probeId
            self.`protocol` = `protocol`
            self.state = state
        }

        public func encode(to encoder: Encoder) throws {
            let request = encoder.userInfo[.awsRequest]! as! RequestEncodingContainer
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encodeIfPresent(self.destination, forKey: .destination)
            try container.encodeIfPresent(self.destinationPort, forKey: .destinationPort)
            request.encodePath(self.monitorName, key: "monitorName")
            try container.encodeIfPresent(self.packetSize, forKey: .packetSize)
            request.encodePath(self.probeId, key: "probeId")
            try container.encodeIfPresent(self.`protocol`, forKey: .`protocol`)
            try container.encodeIfPresent(self.state, forKey: .state)
        }

        public func validate(name: String) throws {
            try self.validate(self.destination, name: "destination", parent: name, max: 255)
            try self.validate(self.destination, name: "destination", parent: name, min: 1)
            try self.validate(self.destinationPort, name: "destinationPort", parent: name, max: 65536)
            try self.validate(self.destinationPort, name: "destinationPort", parent: name, min: 0)
            try self.validate(self.monitorName, name: "monitorName", parent: name, max: 200)
            try self.validate(self.monitorName, name: "monitorName", parent: name, min: 1)
            try self.validate(self.monitorName, name: "monitorName", parent: name, pattern: "^[a-zA-Z0-9_-]+$")
            try self.validate(self.packetSize, name: "packetSize", parent: name, max: 8500)
            try self.validate(self.packetSize, name: "packetSize", parent: name, min: 56)
            try self.validate(self.probeId, name: "probeId", parent: name, pattern: "^probe-[a-z0-9A-Z-]{21,64}$")
        }

        private enum CodingKeys: String, CodingKey {
            case destination = "destination"
            case destinationPort = "destinationPort"
            case packetSize = "packetSize"
            case `protocol` = "protocol"
            case state = "state"
        }
    }

    public struct UpdateProbeOutput: AWSDecodableShape {
        /// The updated IP address family. This must be either IPV4 or IPV6.
        public let addressFamily: AddressFamily?
        /// The time and date that the probe was created.
        public let createdAt: Date?
        /// The updated destination IP address for the probe.
        public let destination: String
        /// The updated destination port. This must be a number between 1 and 65536.
        public let destinationPort: Int?
        /// The time and date that the probe was last updated.
        public let modifiedAt: Date?
        /// The updated packet size for the probe.
        public let packetSize: Int?
        /// The updated ARN of the probe.
        public let probeArn: String?
        /// The updated ID of the probe.
        public let probeId: String?
        /// The updated protocol for the probe.
        public let `protocol`: `Protocol`
        /// The updated ARN of the source subnet.
        public let sourceArn: String
        /// The state of the updated probe.
        public let state: ProbeState?
        /// Update tags for a probe.
        public let tags: [String: String]?
        /// The updated ID of the source VPC subnet ID.
        public let vpcId: String?

        @inlinable
        public init(addressFamily: AddressFamily? = nil, createdAt: Date? = nil, destination: String, destinationPort: Int? = nil, modifiedAt: Date? = nil, packetSize: Int? = nil, probeArn: String? = nil, probeId: String? = nil, protocol: `Protocol`, sourceArn: String, state: ProbeState? = nil, tags: [String: String]? = nil, vpcId: String? = nil) {
            self.addressFamily = addressFamily
            self.createdAt = createdAt
            self.destination = destination
            self.destinationPort = destinationPort
            self.modifiedAt = modifiedAt
            self.packetSize = packetSize
            self.probeArn = probeArn
            self.probeId = probeId
            self.`protocol` = `protocol`
            self.sourceArn = sourceArn
            self.state = state
            self.tags = tags
            self.vpcId = vpcId
        }

        private enum CodingKeys: String, CodingKey {
            case addressFamily = "addressFamily"
            case createdAt = "createdAt"
            case destination = "destination"
            case destinationPort = "destinationPort"
            case modifiedAt = "modifiedAt"
            case packetSize = "packetSize"
            case probeArn = "probeArn"
            case probeId = "probeId"
            case `protocol` = "protocol"
            case sourceArn = "sourceArn"
            case state = "state"
            case tags = "tags"
            case vpcId = "vpcId"
        }
    }
}

// MARK: - Errors

/// Error enum for NetworkMonitor
public struct NetworkMonitorErrorType: AWSErrorType {
    enum Code: String {
        case accessDeniedException = "AccessDeniedException"
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case throttlingException = "ThrottlingException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize NetworkMonitor
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// You do not have sufficient access to perform this action.
    public static var accessDeniedException: Self { .init(.accessDeniedException) }
    /// This operation attempted to create a resource that already exists.
    public static var conflictException: Self { .init(.conflictException) }
    /// The request processing has failed because of an unknown error, exception or failure.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The specified resource does not exist.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// This request exceeds a service quota.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The request was denied due to request throttling
    public static var throttlingException: Self { .init(.throttlingException) }
    /// One of the parameters for the request is not valid.
    public static var validationException: Self { .init(.validationException) }
}

extension NetworkMonitorErrorType: Equatable {
    public static func == (lhs: NetworkMonitorErrorType, rhs: NetworkMonitorErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension NetworkMonitorErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
